package com.dg.river.core.http.interceptor;

import android.content.Context;
import android.provider.Settings;

import com.alibaba.fastjson.JSONObject;
import com.dg.river.BuildConfig;
import com.dg.river.contant.Constant;
import com.dg.river.core.http.ApiManager;
import com.dg.river.core.http.BeanCode;
import com.dg.river.core.http.BeanUtils;
import com.dg.river.core.http.TokenStateEnum;
import com.dg.river.core.manager.UserInfoManager;
import com.dg.river.core.manager.UserInfoMethod;
import com.dg.river.core.util.TextUtil;
import com.dg.river.module.login.activity.LoginActivity;
import com.dg.river.storage.AppSettingManager;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.model.HttpHeaders;
import com.lzy.okgo.request.PostRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * @作者：Hututu
 * @时间：2023/4/13 9:42
 * @描述：内容描述
 * @修改：修改内容
 * @Version:1.0
 */
public class TokenInterceptor implements Interceptor {

    private final Context mContext;

    public TokenInterceptor(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);
        String requestUrl = TextUtil.isEmptyConvert(request.url().toString());
        // 判断token是否失效
        if (response.code() == 401) {
            // 当前token状态为失效
            Constant.tokenState = TokenStateEnum.INVALID;
            // 判断是否需要刷新token
            if (isNeedGetTripToken(requestUrl)) {
                // 获取设备token
                boolean equipmentToken = getEquipmentToken(mContext);
                if (equipmentToken) {
                    // 获取完新的设备token后，用新的token重新请求
                    Request.Builder builder = chain.request().newBuilder();
                    // 如果拼接的地址中包含deviceToken，替换为新获取到的设备token，不需要在header
                    if (requestUrl.contains("deviceToken=")) {
                        String newRequestUrl = "";
                        String[] paramsSplit = requestUrl.split("&", -1);
                        for (String params : paramsSplit) {
                            if (params.contains("deviceToken=")) {
                                newRequestUrl = requestUrl.replace(params, "deviceToken=" + UserInfoManager.getInstance().tripToken(UserInfoMethod.GET, "", false));
                                break;
                            }
                        }
                        builder.url(newRequestUrl);
                    } else {
                        builder.header(Constant.AuthorizationKey, UserInfoManager.getInstance().tripToken(UserInfoMethod.GET, "", true));
                    }
                    Request newRequest = builder.build();
                    return chain.proceed(newRequest);
                }
            } else if (isNeedRefreshToken(requestUrl)) {
                // 执行刷新token
                boolean refreshState = refreshToken(requestUrl);
                if (refreshState) {
                    // 刷新完token后，用新token重新请求
                    Request.Builder builder = chain.request().newBuilder();
                    builder.header(Constant.AuthorizationKey, UserInfoManager.getInstance().userToken(UserInfoMethod.GET, "", true));
                    Request newRequest = builder.build();
                    return chain.proceed(newRequest);
                }
            }
        } else {
            return response;
        }
        LoginActivity.startTop(mContext, "登录失效，请重新登录");
        return response;
    }

    /**
     * 同步锁刷新token
     *
     * @param requestUrl
     * @return
     * @throws IOException
     */
    private synchronized boolean refreshToken(String requestUrl) throws IOException {
        if (Constant.tokenState == TokenStateEnum.INVALID) {
            // 当前token状态为刷新中
            Constant.tokenState = TokenStateEnum.REFRESHING;
            PostRequest<String> postRequest = OkGo.post(ApiManager.Auth.REFRESH_TOKEN);
            postRequest.tag("同步刷新token\n| token过期的请求地址：" + requestUrl);
            postRequest.headers(Constant.TRIP_AUTHORIZATION, Constant.LOGIN_AUTHORIZATION_VALUE);
            postRequest.params("grant_type", "refresh_token");
            postRequest.params("refresh_token", UserInfoManager.getInstance().refreshToken(UserInfoMethod.GET, ""));
            Response postResponse = postRequest.execute();
            ResponseBody body = postResponse.body();
            if (body != null) {
                String json = TextUtil.isEmptyConvert(body.string());
                if (!TextUtil.isEmpty(json)) {
                    return true;
                }
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取设备token
     */
    public synchronized boolean getEquipmentToken(Context mContext) throws IOException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.put(Constant.TRIP_AUTHORIZATION, Constant.TRIP_AUTHORIZATION_VALUE);
        String serialNo = Settings.Secure.getString(mContext.getContentResolver(), Settings.Secure.ANDROID_ID);
        String param = String.format("?serialNo=%s&os=android&appVersion=%s&brand=%s&pushId=%s&grant_type=custom_device&X-Request-Id=", serialNo, BuildConfig.VERSION_NAME, android.os.Build.BRAND, AppSettingManager.getPushGtClientId(mContext));
        PostRequest<String> postRequest = OkGo.post(ApiManager.Device.POST_EQUIPMENT + param);
        postRequest.tag("设备信息");
        postRequest.headers(Constant.TRIP_AUTHORIZATION, Constant.TRIP_AUTHORIZATION_VALUE);
        Response response = postRequest.execute();
        ResponseBody body = response.body();
        if (body != null) {
            String json = body.string();
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject.containsKey("access_token")) {
                String accessToken = jsonObject.getString("access_token");
                UserInfoManager.getInstance().tripToken(UserInfoMethod.SET, accessToken, false);
                return true;
            }
        }
        return false;
    }

    /**
     * 是否需要刷新token
     *
     * @param requestUrl
     * @return
     */
    private boolean isNeedRefreshToken(String requestUrl) {
        // 不需要刷新的API
        List<String> noRefreshApi = new ArrayList<>();
        // 刷新tokenAPI
        noRefreshApi.add(ApiManager.Auth.REFRESH_TOKEN);
        // 判断是需要刷新
        return !noRefreshApi.contains(requestUrl);
    }

    /**
     * 是否需要获取设备token
     *
     * @param requestUrl
     * @return
     */
    private boolean isNeedGetTripToken(String requestUrl) {
        // 不需要刷新的API
        List<String> noGetTripTokenApi = new ArrayList<>();
        // 登录API
        noGetTripTokenApi.add(ApiManager.Auth.POST_LOGIN);
        // 发送短信验证码API
        noGetTripTokenApi.add(ApiManager.Auth.SEND_PHONE_CODE);
        // 忘记密码API
        noGetTripTokenApi.add(ApiManager.Auth.POST_FORGOT_PWD);
        // 判断是需要刷新
        boolean isNeed = false;
        for (String api : noGetTripTokenApi) {
            if (requestUrl.equals(api) || requestUrl.contains(api)) {
                isNeed = true;
                break;
            }
        }
        return isNeed;
    }
}
